package com.example.log_db.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * SpEL表达式解析器
 */
@Slf4j
@Component
public class SpELExpressionEvaluator {

    /**
     * SpEL表达式解析器
     */
    private final ExpressionParser parser = new SpelExpressionParser();

    /**
     * 参数名发现器
     */
    private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

    /**
     * 表达式缓存
     */
    private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);

    /**
     * 解析SpEL表达式
     *
     * @param expressionString 表达式字符串
     * @param method           方法
     * @param args             方法参数
     * @param target           目标对象
     * @param result           方法执行结果
     * @param errorResult      异常信息
     * @return 解析结果
     */
    public String parseExpression(String expressionString, Method method, Object[] args, Object target, Object result, String errorResult) {
        if (expressionString == null || expressionString.isEmpty()) {
            return "";
        }

        try {
            // 如果表达式不包含#，则直接返回
            if (!expressionString.contains("#")) {
                return expressionString;
            }

            // 从缓存中获取表达式
            Expression expression = expressionCache.computeIfAbsent(expressionString, parser::parseExpression);

            // 创建评估上下文
            EvaluationContext context = createEvaluationContext(method, args, target, result, errorResult);

            // 解析表达式
            Object value = expression.getValue(context);
            return value == null ? "" : value.toString();
        } catch (Exception e) {
            log.error("解析SpEL表达式失败: {}", expressionString, e);
            return expressionString;
        }
    }

    /**
     * 创建评估上下文
     */
    private EvaluationContext createEvaluationContext(Method method, Object[] args, Object target, Object result, String errorResult) {
        // 创建方法参数上下文
        EvaluationContext context = new MethodBasedEvaluationContext(target, method, args, parameterNameDiscoverer);

        // 添加方法执行结果
        if (result != null) {
            context.setVariable("result", result);
        }

        // 添加异常信息
        if (errorResult != null) {
            context.setVariable("errorMsg", errorResult);
        }

        // 添加特殊变量
        addSpecialVariables(context);

        return context;
    }

    /**
     * 创建简单评估上下文
     */
    public EvaluationContext createSimpleEvaluationContext(Map<String, Object> variables) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        
        // 添加变量
        if (variables != null) {
            variables.forEach(context::setVariable);
        }
        
        // 添加特殊变量
        addSpecialVariables(context);
        
        return context;
    }

    /**
     * 添加特殊变量
     */
    private void addSpecialVariables(EvaluationContext context) {
        // 可以在这里添加一些全局变量，如当前时间等
        context.setVariable("now", System.currentTimeMillis());
    }
}